﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Parichay.MVC.Controllers
{
    [Authorize]
    public class AuthController : BaseController
    {

        public AuthController()
            : base()
        { }

        protected override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);

            //Include additional Authorization/Security here
            if (!CheckPermissions(filterContext))
            { filterContext.Result = new HttpUnauthorizedResult(); }
        }


        private bool CheckPermissions(AuthorizationContext context)
        {
            string controllerName = "", actionName = "";
            bool rslt = true;

            if (context.RouteData!= null)
            {
                controllerName = context.RouteData.Values["controller"].ToString();
                actionName = context.RouteData.Values["action"].ToString();
            }
            else { return true; }

            HttpRequestBase httpReq = context.HttpContext.Request;
            HttpResponseBase httpResp = context.HttpContext.Response;


            if (httpReq.IsAuthenticated == false)
            {
                //Utilities.TextLog("User is unauthenticated. Exiting Authorization.");
                return true;
            }


            //Only if the current User Is authenticated perform the custom authorization.
            //If the current user is not authenticated, custom security stays Idle.
            if (context.HttpContext.User.Identity.IsAuthenticated)
            {
                bool HasUserPermission = false;
                //Utilities.TextLog("Checking permissions for folder: " + reqFolder + ". And File: " + reqFile);


                string[] permissions = Parichay.Security.ADHSecurityHelper.GetRolesForControllerAction(context.HttpContext.User.Identity.Name, out HasUserPermission, controllerName, actionName);


                //If neither the user has a User Level Permission to the resource
                //And also the Configured Permissions for the resource are not empty.
                //Then check for Role Level Access
                if ((!HasUserPermission) && (permissions.Length != 0))
                    if (!((permissions.Length == 1) && (string.IsNullOrEmpty(permissions[0]))))  //Sometimes a singular string with blank value was returned.
                    {
                        //If User has none of the Allowed Roles for a particular resource. Access will be denied. 
                        if (!MatchUserRolesToPermissions(context.HttpContext.User, permissions))
                        {
                            string message = string.Format("User {0} does not have permission to access the Action Name: {1} located in Controller {2}"
                                , context.HttpContext.User.Identity.Name, actionName, controllerName);

                            System.Diagnostics.Trace.TraceInformation(message);
                            Parichay.Domain.Interface.Data.ILogRepository logger = StructureMap.ObjectFactory.GetInstance<Parichay.Domain.Interface.Data.ILogRepository>();
                            logger.Log(new System.Security.SecurityException(message));
                            //.TextLog(message);
                            return false;
                            //throw new System.Security.SecurityException(message);
                        }
                    }
            }

            return rslt;
        }

        /// <summary>
        /// If any of the roles for the current user match with the Allowed roles for a particular resource (Folder\File.aspx) the user is allowed access.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <param name="roles">List of allowed Roles (configured for a particular resource{Folder\File.aspx}) to be compared with Input user's roles.</param>
        /// <returns>
        /// 	<c>true</c> if any of User's roles match with Allowed roles for a particular resource; otherwise, <c>false</c>.
        /// </returns>
        private bool MatchUserRolesToPermissions(System.Security.Principal.IPrincipal user, string[] roles)
        {
            if (user == null)
                return false;

            foreach (string role in roles)
            {
                if (user.IsInRole(role))
                {
                    return true;
                }
            }

            return false;
        }

    }
}
